package org.smart4j.framework;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.smart4j.framework.bean.*;
import org.smart4j.framework.helper.*;
import org.smart4j.framework.util.CodecUtil;
import org.smart4j.framework.util.JsonUtil;
import org.smart4j.framework.util.ReflectionUtil;
import org.smart4j.framework.util.StreamUtil;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求转发器
 * @author luoyong
 * @date 2018-11-19下午 9:20
 */
@WebServlet(urlPatterns = "/*",loadOnStartup = 0)
public class DispatcherServlet extends HttpServlet {

    @Override
    public void init(ServletConfig servletConfig) throws ServletException{

        //初始化helper类
        HelperLoader.init();

        //获取servletContext 对象用于注册servlet
        ServletContext servletContext = servletConfig.getServletContext();

        //注册jsp servlet
        ServletRegistration jspServlet = servletContext.getServletRegistration("jsp");

        jspServlet.addMapping(ConfigHelper.getAppJspPath()+"*");

        //注册静态资源的默认servlet
        ServletRegistration defaultServlet = servletContext.getServletRegistration("default");
        defaultServlet.addMapping(ConfigHelper.getAppAssetPath()+"*");
        //初始化apache commons 上传对象
        UploadHelper.init(servletContext);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        ServletHelper.init(req,resp);
        try {
            String requestMethod  = req.getMethod().toLowerCase();
            String requestPath = req.getPathInfo();
            Handler handler = ControllerHelper.getHandler(requestMethod, requestPath);
            if (handler != null){
                Class<?> controllerClass = handler.getControllerClass();
                Object controllerBean = BeanHelper.getBean(controllerClass);

                ParamNew param =null;
                if (UploadHelper.isMultipart(req)){
                    param = UploadHelper.createParam(req);
                }else{
                    param = RequestHelper.createParam(req);
                }
                Method actionMethod = handler.getActionMethod();
                Class<?>[] parameterTypes = actionMethod.getParameterTypes();
                Object result ;
                if (ArrayUtils.isNotEmpty(parameterTypes)){

                    result = ReflectionUtil.invokeMethod(controllerBean, actionMethod, param);
                }else{
                    result = ReflectionUtil.invokeMethod(controllerBean, actionMethod);
                }

                if (result instanceof View){
                    handlerView(req, resp, (View) result);
                }else if(result instanceof Data){
                    handlerData(resp, (Data) result);
                }
            }


        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            ServletHelper.destory();
        }

    }

    private void handlerData(HttpServletResponse resp, Data result) throws IOException {
        //返回json数据
        Data data = result;
        Object model = data.getModel();
        if (model!=null){
            resp.setContentType("application/json");
            resp.setCharacterEncoding("UTF-8");
            PrintWriter writer = resp.getWriter();
            String json = JsonUtil.toJson(model);
            writer.write(json);
            writer.flush();
            writer.close();
        }
    }

    private void handlerView(HttpServletRequest req, HttpServletResponse resp, View result) throws IOException, ServletException {
        //返回jsp页面
        View view = result;
        String path = view.getPath();
        if (path.startsWith("/")){
            resp.sendRedirect(req.getContextPath()+path);
        }else{
            //转发
            Map<String, Object> model = view.getModel();
            for (Map.Entry<String,Object> entry : model.entrySet()){
                req.setAttribute(entry.getKey(),entry.getValue());
            }
            req.getRequestDispatcher(ConfigHelper.getAppJspPath()+path).forward(req,resp);
        }
    }


}
